


/*-----------  ----------------------------- ----------------------------- 
	


----------------------------------------------------------  */


#include "cjson_api_readAttr.h"
#include "dev_liquid_level.h"
#include "gui_cjson_api.h"
#include "gw_ktj_tcp_client.h"
#include "iotv30_tcp_client.h"
#include "string.h"
#include "iotv30_config.h"

 //#include  "../protocol/PLC.h"
#include "uart_printf.h"
#include "user_flash.h"

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

//./src/include/
//#include "data_struct.h"

//#include "../../../../src/include/data_struct.h"
///home/ubuntu/t0/prj/hw/shome-pack/src/project/so_iotv30/iotv30/
///home/ubuntu/t0/prj/hw/shome-pack/src/include



#include  "iot_node_func.h"
#include  "iot_node.h"



 //static iot_NodeConfigObj_u   iot_NodeConfigObj;//平台配置的节点---

  iot_NodeConfigObj_u   iot_NodeConfigObj;//平台配置的节点---


static  uint8_t ucNumOfNode ;        //节点的个数 ---
static	uint8_t node_param_save_flash_enable;   //flash 参数保存标记    


//------保存用户参数-------
static void iot_Node_SaveParam(void);



//把节点配置数据从idx_s位置移动到 idx_t 位置 
//输入参数 要求 idx_s > idx_t 从后面往前面移动,最后的数据清0
//返回值 0=失败，非0=成功
static uint8_t MoveNode( uint8_t idx_t ,uint8_t idx_s,uint8_t node_total);




//把无效配置节点去掉
static void RemoveNullNode_Fast(void)	;

//把无效配置节点去掉
static void RemoveNullNode(void);

//把无效配置节点去掉==每次只挪动1个非0节点
static void RemoveNullNode_Quick(void);


void iot_Node_Init(void)
{
  FILE * pFile;
	
	ucNumOfNode = 0 ; 
	node_param_save_flash_enable = 0;	
	
	memset(iot_NodeConfigObj.Buffer,0,sizeof(iot_NodeConfigObj_u) );
	

    logout( "%s\n",__FUNCTION__ );


  //打开文件
   //pFile = fopen ("./user_flash.txt","r+b");//以（读写）形式打开文件    
  // pFile = fopen (USER_FLASH_FILE_PATH,"r+b");//以（读写）形式打开文件 

   pFile = FLASH_Unlock(); 

  //文件操作
	if (  NULL == pFile)
	{// //打开失败---文件不存在
 
	    UartPrintString( "fopen ");
		UartPrintString( USER_FLASH_FILE_PATH);
		UartPrintString( "fail\n" );

	}else{

		 //ReadDataFromFlash_8Bits(pFile, (uint8_t*)&iot_NodeConfigObj.Buffer[0], FLASH_NODE_START_ADR, sizeof( iot_NodeConfigObj_u ) );	

		if( 0== FlashWriteCheck(pFile, FLASH_NODE_HEAD_ADR) 	)//0x08079800
		{ ////第一次上电====默认参数       
			
			// iot_Node_SaveParam( );		 		
			iot_Node_ParamSaveFlashEnable( );		
		}else{ 	
		
			ReadDataFromFlash_8Bits(pFile, (uint8_t*)&iot_NodeConfigObj.Buffer[0], FLASH_NODE_START_ADR, sizeof( iot_NodeConfigObj_u ) );	
			ReadDataFromFlash_8Bits(pFile,(uint8_t*)&ucNumOfNode, FLASH_NODE_TOTAL_ADR, 1);	//	读取配置的节点总数	
				
		}
			
	}
			

     iot_reset_device_flag( );//debug 20191107-	
	
	//iot_Node_Test( );
    //iot_Node_Test_tick_min( );  //just for testing
}




void iot_Node_ParamSaveFlashEnable(void)
{
	 node_param_save_flash_enable = 1;
	
}


//保存白名单到PLC CCO 
void iot_Node_ParamSaveToPLC(void)
{
	// PLC_LogicCmdModifyCfgNode( );
}


/*-----------断路器存储信息---------------------*/

 
//------保存用户参数-------
static void iot_Node_SaveParam(void)
{	
FILE * pFile;	

 uint8_t  buf[2];	
 uint16_t tmp;	

     pFile = FLASH_Unlock( );
	
	if(NULL == pFile)
	{
		return ;
	}
	
    LOG_NAME();
			
	buf[0] = (uint8_t)FLASH_VALID_FLAG1;
	buf[1] = FLASH_VALID_FLAG1>>8;
		
    /* 写FLASH头 */
  WriteDataToFlash_8Bits(pFile,&buf[0], FLASH_NODE_HEAD_ADR, 2);					
					

	
	/* 写结点数量 */
	buf[0] = ucNumOfNode;
	buf[1] = 0;
	WriteDataToFlash_8Bits(pFile,&buf[0], FLASH_NODE_TOTAL_ADR, 2);
	
	ReadDataFromFlash_8Bits( pFile,&buf[0], FLASH_NODE_TOTAL_ADR, 2 );		//	for test



  tmp = sizeof( iot_NodeConfigObj_u ) ;//0x09F6=2550

	buf[0] =tmp&0xFF;
	buf[1] =tmp>>8;

	WriteDataToFlash_8Bits(pFile, (uint8_t*)&iot_NodeConfigObj.Buffer[0] , FLASH_NODE_START_ADR, tmp ); 
    
	//FLASH_Lock();
	
	
	//----for test-----
	ReadDataFromFlash_8Bits(pFile,  (uint8_t*)&iot_NodeConfigObj.Buffer[0], FLASH_NODE_START_ADR, tmp );	//	for test

	FLASH_Lock(pFile);  

}





void iot_Node_UpdateParamProcess(void)
{

  if( 0 == node_param_save_flash_enable )
	   return;
	
	node_param_save_flash_enable  = 0;
	
	 LOG_NAME();
  iot_Node_SaveParam( );		
	
  //PLC_LogicCmdModifyCfgNode( );		

}





uint8_t  iot_Node_GetNum(void)
{
  return ucNumOfNode  ;

}



void  iot_Node_SetNum(uint8_t num)
{
   ucNumOfNode =  num;

}



//返回值非0，表示查找成功；返回值0，表示查找失败，不存在该编号
uint8_t iot_Node_GetIndex( uint16_t sub_uid, uint8_t* index )
{
uint8_t idx,num ;
	
   num = ucNumOfNode; 
 
//#if SMART_ENABLE
//	 for(idx=num;idx--; )	
//#else
//	 for(idx=0;idx<num;idx++)	
//#endif	
	
	 for(idx=0;idx<num;idx++)		
	 {	 		
		if( sub_uid ==  iot_NodeConfigObj.Node[idx].Config.sub_uid )
		{
			*index = idx;
			return 1;	 
		}
	 }
	 
 return 0;	 
	 
}



/**
 * @brief 
 *    ////重新计数------每次只发送 MAX_NUM_IN_PACKET 个节点的数据-------
     ////当前是连包发送，没有分帧发送处理，
 * @param  idx 配置节点的下标索引
 * @return NodeConfig_st* 返回配置节点的数据结构指针, ==NULL 表示查找失败 ，  !NULL 表示查找成功
 */

 iot_NodeConfig_st* iot_Node_Get_topoinfo(uint8_t idx)
{
    if(idx >= ucNumOfNode )
    {
        return NULL;
    }

return &(iot_NodeConfigObj.Node[idx].Config);
	
}




#if NODE_MAC_UINT64_ENABLE    




//删除单个节点
void iot_Node_Delete(uint64_t node_id  )
{
  uint8_t idx;
  uint8_t findit;	
		
	findit = 0;
	
//#if SMART_ENABLE
//	 for(idx=ucNumOfNode;idx--; )	
//#else
//	 for(idx=0;idx<ucNumOfNode;idx++)	
//#endif	
	
	for(idx=0;idx<ucNumOfNode;idx++)		
	{
		if(  node_id == iot_NodeConfigObj.Node[idx].Config.sub_mac )
		{//find it
			
			findit = MoveNode( idx ,idx+1, ucNumOfNode );				
		}
	}



	if( findit )
	{		
		 ucNumOfNode--;	//added 2023-06-15	
		
		 iot_Node_ParamSaveFlashEnable( );  ////不再这里调用，则需要手动保存--需要下发0x98保存命令 	
	}
	
    
}






//返回值非0，表示查找成功；返回值0，表示查找失败，不存在该编号
uint8_t iot_Node_GetIndexWithId( uint64_t id, uint8_t* index )
{

uint8_t idx,num ;
	
   num = ucNumOfNode; 
	
//#if SMART_ENABLE
//	 for(idx=num;idx--; )	
//#else
//	 for(idx=0;idx<num;idx++)	
//#endif	

	 for(idx=0;idx<num;idx++)	
	 {	 			 		 
		if( id== iot_NodeConfigObj.Node[idx].Config.sub_mac ) 
		{//find it			
			*index = idx;
			return 1;	 
		}
	 }
	 
 return 0;	 
	 
}


#else 





//删除单个节点
void iot_Node_Delete(uint8_t* node_id  )
{
  uint8_t idx;
  uint8_t findit;	
		
	findit = 0;
	
//#if SMART_ENABLE
//	 for(idx=ucNumOfNode;idx--; )	
//#else
//	 for(idx=0;idx<ucNumOfNode;idx++)	
//#endif	
	
	 for(idx=0;idx<ucNumOfNode;idx++)		
	{
 
		 //返回0=比较结果不相等，返回非0=比较结果相等
			if( IsUint8BuffEQU( node_id, iot_NodeConfigObj.Node[idx].Config.sub_mac , NODE_ID_LEN ) )
			{//find it
				
               findit = MoveNode( idx ,idx+1, ucNumOfNode );				
			}
	 }




	if( findit )
	{		
		 ucNumOfNode--;	//added 2023-06-15	
		
		 iot_Node_ParamSaveFlashEnable( );		  //需要下发0x98保存命令 	
	}
	
    
}






//返回值非0，表示查找成功；返回值0，表示查找失败，不存在该编号
uint8_t iot_Node_GetIndexWithId( uint8_t* id, uint8_t* index )
{
uint8_t idx,num ;
	
   num = ucNumOfNode; 
	
//#if SMART_ENABLE
//	 for(idx=num;idx--; )	
//#else
//	 for(idx=0;idx<num;idx++)	
//#endif	

	 for(idx=0;idx<num;idx++)	
	 {	 			 
		 
		 //返回0=比较结果不相等，返回非0=比较结果相等
			if( IsUint8BuffEQU( id, iot_NodeConfigObj.Node[idx].Config.sub_mac, NODE_ID_LEN ) ) // Config.ID  
			{//find it
				
			    *index = idx;
			    return 1;	 
			 }
	 }
	 
 return 0;	 
	 
}



#endif








//把节点配置数据从idx_s位置移动到 idx_t 位置 
//输入参数 要求 idx_s > idx_t 从后面往前面移动,最后的数据清0
//返回值 0=失败，非0=成功
static uint8_t MoveNode( uint8_t idx_t ,const uint8_t idx_s,uint8_t node_num)
{
	uint8_t i;
	
	if( idx_s <= idx_t)
		 return 0;
		
	//mov 	//memcpy();
	for( i=idx_s;i<node_num; )	
	{
      iot_NodeConfigObj.Node[idx_t++] = iot_NodeConfigObj.Node[i++];		
	}		
	

return 1;
	
}
		



#if 0

//把节点配置数据从idx_s位置移动到 idx_t 位置 
//输入参数 要求 idx_s > idx_t 从后面往前面移动,最后的数据清0
//返回值 0=失败，非0=成功
static uint8_t MoveNode( uint8_t idx_t ,const uint8_t idx_s,uint8_t node_num)
{
	uint8_t i;
	uint16_t detal;
	
	if( idx_s <= idx_t)
		 return 0;
		
	detal = idx_s - idx_t;	
	
	
	//mov 	//memcpy();
	for( i=idx_s;i<node_num; )	
	{
      iot_NodeConfigObj.Node[idx_t++] = iot_NodeConfigObj.Node[i++];		
	}		
	
	
	//clear data

#if  	SMART_ALL_ENABLE	
	
	//sizeof(iot_NodeCore_st)*detal
	//detal = node_num - idx_t ;  //在这里不能(idx_s - idx_t)，因为 idx_t已经改变

	 memset( &iot_NodeConfigObj.Node[idx_t],0, detal* sizeof(iot_NodeCore_st) );	// sizeof(iot_NodeCore_st)*( node_num - idx_t )
	
#else	

	for( i=idx_t;i<node_num;i++)	
	{
     memset( &iot_NodeConfigObj.Node[i],0,sizeof(iot_NodeCore_st) );		
	}		
	
#endif
	

return 1;
	
}
		
#endif



// 不需要continue 语句

//把无效配置节点去掉===每次只移动一段
static void RemoveNullNode_Fast(void)	
{
	uint8_t i,k;
	uint8_t node_num;
	
	node_num = ucNumOfNode;	
	
	for( i=0; i<node_num ; )	
	{
			if( 0 == iot_NodeConfigObj.Node[i].Config.sub_uid )
			{ //节点编号为0
			
			   for( k=i;k<node_num;)	
	           {				
						if( 0 != iot_NodeConfigObj.Node[k].Config.sub_uid)
                       {	//节点编号非0，move		
							 
							MoveNode( i,k, node_num );	//移动一段		
          			         break;		//每次只移动一段	
							 
						 }else {//节点编号为0
				              k++;  //next															 
						 }					 									 				 			
				 }
						
                   node_num = node_num - k + i;		//node_num - (k - i);		 
				 //i = k;//bug----k是原来旧队列的下标，在新队列不适用
				 //i = 0;//debug新队列重新开始
					 i++;  //next node				
				 
			}else{  //节点编号非0	
			   i++;  //next node
			
			}
					
	}
		

 ucNumOfNode = node_num;	
	
	
}




#if 0 //逻辑等价 continue 语句


//把无效配置节点去掉===每次只移动一段
static void RemoveNullNode_Fast(void)	
{
	uint8_t i,k;
	uint8_t node_num;
	
	node_num = ucNumOfNode;	
	
	for( i=0; i<node_num ; )	
	{
			if( 0 != iot_NodeConfigObj.Node[i].Config.sub_uid)
			{	//节点编号非0		
				 i++; //next node
				 continue;	
				
			}else{//节点编号为0	
				
			   for( k=i;k<node_num;)	
	       {				
						 if( 0 == iot_NodeConfigObj.Node[k].Config.sub_uid)
						 {//节点编号为0
				         k++;  //next
								continue;	
							 
						 }else{//节点编号非0，move		
						 							 
								MoveNode( i,k, node_num );		
          			break;		//每次只移动一段		 
						 }					 				 
				
				 }
						
         node_num = node_num - k + i;		//node_num - (k - i);		 
				 //i = k;//bug----k是原来旧队列的下标，在新队列不适用
				 i = 0;//debug新队列重新开始
										 
			}
					
	}
		

 ucNumOfNode = node_num;	
	
	
}



#endif




//把无效配置节点去掉==每次只挪动1个节点
static void RemoveNullNode(void)
{
	uint8_t i,k;
	uint8_t node_num;	
	
	node_num = ucNumOfNode;
		
	for( i=0; i<node_num; )	
	{
		if( 0 == iot_NodeConfigObj.Node[i].Config.sub_uid)
		{ //节点编号为0,不能i++;
						
				node_num--;  //节点总数减1===每次只挪动1个节点
			for( k=i;k<node_num;k++)	
			{				
				iot_NodeConfigObj.Node[k] = iot_NodeConfigObj.Node[k+1];	//因为k+1的节点编号尚未检测,所以不能i++检测下一个	
			}	

				//最后一个节点数据清0===每次只挪动1个节点
				memset( &iot_NodeConfigObj.Node[k],0,sizeof(iot_NodeCore_st) );						
				
		}else{  //节点编号非0	
			i++;  //next node
		
		}
			
						
	}
		
 ucNumOfNode = node_num;
	
}


#if 0  //逻辑等价 continue 语句

//把无效配置节点去掉==每次只挪动1个节点
static void RemoveNullNode(void)
{
	uint8_t i,k;
	uint8_t node_num;	
	
	node_num = ucNumOfNode;
		
	for( i=0; i<node_num; )	
	{
			if( 0 != iot_NodeConfigObj.Node[i].Config.sub_uid)
			{	//节点编号非0		
				 i++; //next node
				 continue;	
				
			}else{  //节点编号为0,不能i++;
						 
         node_num--;  //节点总数减1===每次只挪动1个节点
			   for( k=i;k<node_num;k++)	
	       {				
						 iot_NodeConfigObj.Node[k] = iot_NodeConfigObj.Node[k+1];	//因为k+1的节点编号尚未检测,所以不能i++检测下一个	
				 }	

				 //最后一个节点数据清0===每次只挪动1个节点
				 memset( &iot_NodeConfigObj.Node[k],0,sizeof(iot_NodeCore_st) );	
											 				 
			}
						
	}
		
 ucNumOfNode = node_num;
	
}

#endif










//void RefreshNodeQueue(void)

//把无效配置节点去掉==每次只挪动1个非0节点
static void RemoveNullNode_Quick(void)
{
	uint8_t p0;  //0节点的下标-----始终指向0节点
	uint8_t p1;	 //非0节点的下标---始终指向非0节点

	uint8_t node_num;	
	
	node_num = ucNumOfNode;
		
	for( p0=0; p0<node_num; p0++ )	
	{
			if( 0 == iot_NodeConfigObj.Node[p0].Config.sub_uid)
      {  //节点编号为0
						 
			   for( p1=p0 +1;p1<node_num;p1++)	
	       {	//查找非0节点
					 
							if( 0 != iot_NodeConfigObj.Node[p1].Config.sub_uid)
							{	//节点编号非0	,移动非0节点到		
								
									iot_NodeConfigObj.Node[p0] = iot_NodeConfigObj.Node[p1];	
								
									 //把该节点标记为0,下次就不需要再重复移动------
								  //iot_NodeConfigObj.Node[p1].Config.sub_uid= 0;   //---标记已经移动---下次不需在移动
						      memset( &iot_NodeConfigObj.Node[p1],0,sizeof(iot_NodeCore_st) );	
								
								  break; //每次只移动1个非0节点----注意不是一段--因为数据段里面可能有0节点，0节点也移动了
							 }									 
				  }


					
					if( p1 == node_num )
					{ //判断是否查找到末尾
						//有些数据尚未清0
						
					  ucNumOfNode = p0;	//--p0始终指向0节点,故p0即为当前的节点总数
					  break; // 挪动结束
					}
									 
			}
			
	}
	
	
	
}		


#if 0
	
	  /* 清除无效终端节点信息 */
	  for(ucIndex = 0; ucIndex < node_num; ucIndex++)
	  {

				
		    /* 找出清除了的ID的空位 */
		    if (ulID!= 0){
			      continue;//跳过本次循环 继续下次循环
		    }
				
				
				
				
		    /* 把节点空位之后的节点前移到该空位上来 */
	        for(ucCNT = ucIndex; ucCNT < g_ucSumOfNode; ucCNT++)
		    {

			      if (ulID != 0){  //-------------------------------------------每次只移动一个非0节点----注意不是一段--因为数据段里面可能有0节点，0节点也移动了
							
				        /* 把后面的节点数据移到前面来 */
				        for(ucCNT2 = 0; ucCNT2 < NODE_STRUCT_MAX; ucCNT2++){
					          g_ucNodeData[ucIndex][ucCNT2] = g_ucNodeData[ucCNT][ucCNT2];
				        }
				        /*删除后面的节点数据*/   //---------------------------------标记已经移动---下次不需在移动
				        for(ucCNT2 = 0; ucCNT2 < NODE_STRUCT_MAX; ucCNT2++){
					          g_ucNodeData[ucCNT][ucCNT2] = 0;
				        }
				        break;
			      }		
		    }
		    /* 判断节点数据是否移动完毕 */
		    if (ucCNT == g_ucSumOfNode){
			      g_ucSumOfNode = ucIndex;  /* 确定新的节点个数 */
			      break;
		    }
	  }


#endif










//删除某个组号----所有的节点都被删除???!!!

//删除组节点
void iot_Node_DeleteGroup(uint8_t group)
{
  uint8_t idx;
  uint8_t findit;	
		
	findit = 0;
	
//#if SMART_ENABLE
//	for( idx=ucNumOfNode;idx--;)		
//#else
//	for(idx=0;idx<ucNumOfNode;idx++)	
//#endif	
	
	
	for(idx=0;idx<ucNumOfNode;idx++)		
	{
			if( group == iot_NodeConfigObj.Node[idx].Config.group )
			{			
				
//#if  	SMART_ALL_ENABLE	
//	
//	     	 iot_NodeConfigObj.Node[idx].Config.sub_uid= 0;	//清除节点配置的编号---标记无效配置节点
//#else			
//         memset( &iot_NodeConfigObj.Node[idx],0,sizeof(iot_NodeCore_st) );		//清除节点配置所有数据
//#endif			
							
               memset( &iot_NodeConfigObj.Node[idx],0,sizeof(iot_NodeCore_st) );		//清除节点配置所有数据
							
				 findit = 1;
			}
	}
	
	
    
       if ( 0 != findit )
		{//把无效配置节点去掉
			  		
#if  	SMART_ALL_ENABLE	
	
	     // RemoveNullNode_Fast( );
			  RemoveNullNode_Quick( );
#else			
        RemoveNullNode( );
#endif			
			
 //     RemoveNullNode( );			
        iot_Node_ParamSaveFlashEnable( );   //需要下发0x98保存命令 								
    }
		
    
}



//根据节点类型，在指定的组节点
void iot_Node_DeleteGroup_ByType(uint8_t group,uint16_t node_type)
{
  uint8_t idx;
  uint8_t findit;	
		
	findit = 0;
	
//#if SMART_ENABLE
//	for( idx=ucNumOfNode;idx--;)		
//#else
//	for(idx=0;idx<ucNumOfNode;idx++)	
//#endif	
	
	
	for(idx=0;idx<ucNumOfNode;idx++)		
	{
			if( (group == iot_NodeConfigObj.Node[idx].Config.group ) &&( node_type == iot_NodeConfigObj.Node[idx].Config.node_type ) )
			{						
							
//#if  	SMART_ALL_ENABLE	
//	
//	     	    iot_NodeConfigObj.Node[idx].Config.sub_uid= 0;	//清除节点配置的编号---标记无效配置节点
//#else			
//              memset( &iot_NodeConfigObj.Node[idx],0,sizeof(iot_NodeCore_st) );		//清除节点配置所有数据
//#endif

                 memset( &iot_NodeConfigObj.Node[idx],0,sizeof(iot_NodeCore_st) );		//清除节点配置所有数据							
				 findit = 1;
			}
	}
	
	
    
       if ( 0 != findit )
		{//把无效配置节点去掉
			  		
#if  	SMART_ALL_ENABLE	
	
	     // RemoveNullNode_Fast( );
			  RemoveNullNode_Quick( );
#else			
        RemoveNullNode( );
#endif			
			
 //     RemoveNullNode( );
			
		 iot_Node_ParamSaveFlashEnable( );   //需要下发0x98保存命令 		
						
     }	
    
}












//删除某个类型的节点
void iot_Node_DeleteType(uint16_t node_type)
{
  uint8_t idx;
  uint8_t findit;	
		
	findit = 0;
	
//#if SMART_ENABLE
//	for( idx=ucNumOfNode;idx--;)		
//#else
//	for(idx=0;idx<ucNumOfNode;idx++)	
//#endif	
	
	
	for(idx=0;idx<ucNumOfNode;idx++)		
	{
			if( node_type == iot_NodeConfigObj.Node[idx].Config.node_type )
			{			
				
//#if  	SMART_ALL_ENABLE	
//	
//	     	    iot_NodeConfigObj.Node[idx].Config.sub_uid= 0;	//清除节点配置的编号---标记无效配置节点
//#else			
//              memset( &iot_NodeConfigObj.Node[idx],0,sizeof(iot_NodeCore_st) );		//清除节点配置所有数据
//#endif			
							
                memset( &iot_NodeConfigObj.Node[idx],0,sizeof(iot_NodeCore_st) );		//清除节点配置所有数据
							
				findit = 1;
			}
	}
	
	
    
       if ( 0 != findit )
		{//把无效配置节点去掉
			  		
#if  	SMART_ALL_ENABLE	
	
	     // RemoveNullNode_Fast( );
			RemoveNullNode_Quick( );
#else			
            RemoveNullNode( );
#endif			
			
 //         RemoveNullNode( );
			
			iot_Node_ParamSaveFlashEnable( );   //自动保存命令 					
			
        }
		
    
}



//清空所有配置节点
void iot_Node_Clear(void )
{
  //iot_Node_SetNum( 0 );
	ucNumOfNode = 0 ; 
	
	memset(iot_NodeConfigObj.Buffer,0,sizeof(iot_NodeConfigObj_u) );

	iot_Node_ParamSaveFlashEnable( );		 
	

}







//先查找有没有相同的ID节点，有则覆盖，没有则新增
//还需要增加返回结果------以判断参数是否合法---
void iot_Node_Add(void* nod  )
{
  uint8_t idx;
  uint8_t findit;	

  dev_mod_info_t info;
  iot_NodeCfg_Com_u* 	com =NULL;
	
	com = (iot_NodeCfg_Com_u* )nod;	//按数据结构解析
	
	findit = 0;
	

    printf("ucNumOfNode=%d before add\n",ucNumOfNode);


//#if SMART_ENABLE
//	 for(idx=ucNumOfNode;idx--; )	
//#else
//	 for(idx=0;idx<ucNumOfNode;idx++)	
//#endif	


	 for(idx=0;idx<ucNumOfNode;idx++)		
	{//查找节点是否存在

#if NODE_MAC_UINT64_ENABLE    		
			if( com->Node.sub_uid == iot_NodeConfigObj.Node[idx].Config.sub_uid )
#else
			if( IsUint8BuffEQU( com->Node.sub_mac , iot_NodeConfigObj.Node[idx].Config.sub_mac , NODE_ID_LEN ) )
#endif
			{//find it---节点存在则覆盖

				  if( com->Node.group != iot_NodeConfigObj.Node[idx].Config.group )
				  {
					 iot_NodeConfigObj.Node[ucNumOfNode].Flag.bit.group_added = 0; //标记清0
				  }
				
				
				 iot_NodeConfigObj.Node[idx].Config = com->Node ;
				
                 findit = 1;	
				 
				 //  dev_module_set_attr( uint16_t sub_uid,void* attr_in);   //IotModel			 
				//   dev_module_set_attr_with_index( uint8_t index,void* attr_in);   


                   ///------------可以在这里增加注册对应的节点指针---------------------
                   ///-------------for testing---------------------
		
					// printf("add node cover idx=%d\n",idx);
					// liquid_add_obj( idx,com->Node.channel,com->Node.sub_mac&0x0FF );
					 dev_module_add_obj( idx,com->Node.channel,com->Node.sub_mac &0x0FF,com->Node.node_type );

				    // liquid_set_attr( idx,IotModel* attr);//还需要设置设备地址，通道编号
					//iot_set_device_online_state_with_index( idx, 1); ///------------just for testing---------------------
					 iot_Node_ParamSaveFlashEnable( );		//不再这里调用，则需要手动保存

//iot_get_mod_info_with_index
 #if  CJSON_WHITE_LIST_ENABLE  
					 if( iot_get_mod_info_with_index( idx , &info)  )  
					 {
						json_write_cmd_set_white_list( &info, com->Node.node_type) ;
					 }
						 
#endif				
					 

			}
	 }
	
	

	if( 0==findit )
	{	//节点不存在则在末尾添加节点
	 
		 iot_NodeConfigObj.Node[ucNumOfNode].Config = com->Node;
		 iot_NodeConfigObj.Node[ucNumOfNode].Flag.all = 0; //标记清0
		
		////还需要判断返回结果
		//liquid_add_obj( idx,com->Node.channel,com->Node.sub_mac &0x0FF );
		dev_module_add_obj( idx,com->Node.channel,com->Node.sub_mac &0x0FF,com->Node.node_type );

		// liquid_set_attr( idx,IotModel* attr);//还需要设置设备地址，通道编号

		//iot_set_device_online_state_with_index( idx, 1); ///------------just for testing---------------------
	

		 ucNumOfNode++;
		
		iot_Node_ParamSaveFlashEnable( );		//不再这里调用，则需要手动保存


 #if  CJSON_WHITE_LIST_ENABLE  
		if( iot_get_mod_info_with_index( idx , &info)  )  
		{
		   json_write_cmd_set_white_list( &info, com->Node.node_type) ;
		}
			
#endif	


	}
	
	
   //保存参数 
  // iot_Node_ParamSaveFlashEnable( );		//不再这里调用，则需要手动保存
	
	
}


uint8_t PLC_GetNodeAmout(void )
{

	return 8;
}

uint8_t PLC_SetNodeAmout(uint8_t num )
{

	return 8;
}


void PLC_LogicClearCmd(void )
{

	return ;
}





//#define   SMART_ENABLE             (0x01u)    //smart			
//开放性组网
void iot_Node_Create(void)
{ 
 uint8_t i;
 uint8_t topo_amout	;	
		
Lamp_NodeCfgFlags_u flag;

#if !NODE_MAC_UINT64_ENABLE   
NodeCfg_Com_u	node_cfg;
#endif

		flag.all = 0;
		flag.bit.online           = 1;
		flag.bit.white_name_added = 1; 
		flag.bit.group_added      = 0;//debug---202306601--还需要把自动生成的组号同步下发给节点 


	//	PLCObj.WhiteAmout = topo_amout = PLC_GetNodeAmout( );    	
        topo_amout = PLC_GetNodeAmout( );  

	  iot_Node_SetNum(topo_amout);
	
#if !NODE_MAC_UINT64_ENABLE   	


	node_cfg.Node.sub_mac[0]  = 11;  	
	node_cfg.Node.sub_mac[1]  = 0;  
	node_cfg.Node.sub_mac[2]  = 0;  	
	node_cfg.Node.sub_mac[3]  = 5;  
	node_cfg.Node.sub_mac[4]  = 0;  	
	node_cfg.Node.sub_mac[5]  = 0;  
	    
#endif

		 for(i = 0; i < topo_amout; i++)
		{							

#if NODE_MAC_UINT64_ENABLE   
		    iot_NodeConfigObj.Node[i].Config.sub_mac  = 0x123456789A00 + i;  
		    iot_NodeConfigObj.Node[i].Config.link_mac = 0x123456789000 + i;  
#else
            node_cfg.Node.sub_mac[0] = i;
            memcpy(&iot_NodeConfigObj.Node[i].Config.sub_mac[0],	&(node_cfg.Node.sub_mac[0]) , 6 ); 

			//memcpy(&iot_NodeConfigObj.Node[i].Config.sub_mac[0],	&(Lamp_NodeData[i].Core.ID[0]) , 6 );    //??????

#endif


			iot_NodeConfigObj.Node[i].Config.group  = NODE_CREATE_DEFAULT_GROUP;        // 默认组号为1   Lamp_NodeData[i].Param.Group ;
			iot_NodeConfigObj.Node[i].Config.node_type   = IOT_SENSOR_liquid;             // 默认类型   Lamp_NodeData[i].Param.DeviceType ; //0x28;	//160W LED电源		

			iot_NodeConfigObj.Node[i].Config.sub_uid    = i+1;                          // 节点编号			
	
			iot_NodeConfigObj.Node[i].Flag.all  = flag.all;   ///?????

			iot_NodeConfigObj.Node[i].Config.channel = dev_chan_485_1;  
			iot_NodeConfigObj.Node[i].Config.link_channel = dev_chan_485_1;  

		}
			

   iot_Node_ParamSaveFlashEnable( );				
		
   PLC_LogicClearCmd( );
			
}




//#define   SMART_ENABLE             (0x01u)    //smart			

//针对PLC节点数据
void iot_Node_Destroy(void)
{ 
	
 uint8_t i;
 uint8_t topo_amout	;	

	topo_amout = PLC_GetNodeAmout( );
	
		 for(i = 0; i < topo_amout; i++)
		{					
			//memset( &(Lamp_NodeData[i]),0 , sizeof(Lamp_NodeData_st) );/////????????

		}
		
	PLC_SetNodeAmout( 0 );

		
}



//Iot_NodeCfg[NODE_CFG_NUM_MAX];

//7.3.2.1下发网关子设备拓扑 60H 


#define  NODE95_TEST_GROUP_1_QT   (5)
#define  NODE95_TEST_GROUP_2_QT   (7)
#define  NODE95_TEST_GROUP_3_QT   (3)



void iot_Node_Test(void)
{ 
uint8_t k,offset;

iot_NodeCfg_Com_u	node_cfg;

memset(node_cfg.Buffer,0,sizeof(iot_NodeCfg_Com_u)  );

//清空所有配置节点
 //iot_Node_Clear( );


#if NODE_MAC_UINT64_ENABLE   
	node_cfg.Node.sub_mac   = 0x123456789A00 + 0;  
	node_cfg.Node.link_mac  = 0x123456789B00 + 0;  	
#else	

   node_cfg.Node.sub_mac[0]  = 11;  	
   node_cfg.Node.sub_mac[1]  = 0;  
   node_cfg.Node.sub_mac[2]  = 0;  	
   node_cfg.Node.sub_mac[3]  = 5;  
   node_cfg.Node.sub_mac[4]  = 0;  	
   node_cfg.Node.sub_mac[5]  = 0;  
	    
#endif



	node_cfg.Node.node_type   = IOT_SENSOR_liquid;             // 默认类型   Lamp_NodeData[i].Param.DeviceType ; //0x28;	//160W LED电源		
	node_cfg.Node.sub_uid    = 1;                          // 节点编号			
	node_cfg.Node.channel = dev_chan_485_1;  
	node_cfg.Node.link_channel = dev_chan_485_1;  

    node_cfg.Node.group  = 1;
	
//----添加组号1节点-------
   offset = 1;
   node_cfg.Node.group  = 1;
	 
	for(k=0;k<NODE95_TEST_GROUP_1_QT;k++)
	{
 
#if NODE_MAC_UINT64_ENABLE   
	     node_cfg.Node.sub_mac   = 0x123456789A00  + offset +k;  
	     node_cfg.Node.link_mac  = 0x123456789B00  + offset +k;  			 
#else				
		 node_cfg.Node.sub_mac[0]   = 10+offset+k; 	
		 node_cfg.Node.link_mac[0]  = 80+offset+k; 			 
#endif
	     node_cfg.Node.sub_uid    = 1+offset +k;      // 节点编号	

		 iot_Node_Add( &node_cfg )	;
         //iot_set_device_online_state_with_index( uint8_t index, uint8_t state);

	}

	
//----添加组号2节点-------
   offset += NODE95_TEST_GROUP_1_QT;
   node_cfg.Node.group  = 2;
	 
	for(k=0;k<NODE95_TEST_GROUP_2_QT;k++)
	{

#if NODE_MAC_UINT64_ENABLE   
	     node_cfg.Node.sub_mac   = 0x123456789A00  + offset +k;  
	     node_cfg.Node.link_mac  = 0x123456789B00  + offset +k;  			 
#else				
		 node_cfg.Node.sub_mac[0]   = 10+offset+k; 	
		 node_cfg.Node.link_mac[0]  = 80+offset+k; 			 
#endif
	     node_cfg.Node.sub_uid    = 1+offset +k;      // 节点编号	


		 iot_Node_Add( &node_cfg )	;

	}
	
	
//----添加组号3节点-------
   offset += NODE95_TEST_GROUP_2_QT;
   node_cfg.Node.group  = 3;
	 
	for(k=0;k<NODE95_TEST_GROUP_3_QT;k++)
	{
 
#if NODE_MAC_UINT64_ENABLE   
	     node_cfg.Node.sub_mac   = 0x123456789A00  + offset +k;  
	     node_cfg.Node.link_mac  = 0x123456789B00  + offset +k;  			 
#else				
		 node_cfg.Node.sub_mac[0]   = 10+offset+k; 	
		 node_cfg.Node.link_mac[0]  = 80+offset+k; 			 
#endif
	     node_cfg.Node.sub_uid    = 1+offset +k;      // 节点编号	

		 iot_Node_Add( &node_cfg )	;

	}
	
	

#if  0   //------test ok---2024-11-07--	

  offset = 1;
  k = 0;
 
#if NODE_MAC_UINT64_ENABLE   
	     node_cfg.Node.sub_mac   = 0x123456789A00  + offset +k;  
	     node_cfg.Node.link_mac  = 0x123456789B00  + offset +k;  			 
#else				
		 node_cfg.Node.sub_mac[0]   = 10+offset+k; 	
		 node_cfg.Node.link_mac[0]  = 80+offset+k; 			 
#endif
	     node_cfg.Node.sub_uid    = 1+offset +k;      // 节点编号	


   iot_Node_Delete( node_cfg.Node.sub_mac );//删除单个节点

	
	
  offset = 1;
  k = 3;

#if NODE_MAC_UINT64_ENABLE   
	     node_cfg.Node.sub_mac   = 0x123456789A00  + offset +k;  
	     node_cfg.Node.link_mac  = 0x123456789B00  + offset +k;  			 
#else				
		 node_cfg.Node.sub_mac[0]   = 10+offset+k; 	
		 node_cfg.Node.link_mac[0]  = 80+offset+k; 			 
#endif
	     node_cfg.Node.sub_uid    = 1+offset +k;      // 节点编号	


   iot_Node_Delete( node_cfg.Node.sub_mac  );//删除单个节点
	
	

//删除组节点
 iot_Node_DeleteGroup( 2 );
	
	
//删除组节点
 iot_Node_DeleteGroup( 1 );	
	
	
//----添加组号2节点-------
   offset += NODE95_TEST_GROUP_1_QT;
   node_cfg.Node.group  = 2;
	 
	for(k=0;k<NODE95_TEST_GROUP_2_QT;k++)
	{

#if NODE_MAC_UINT64_ENABLE   
	     node_cfg.Node.sub_mac   = 0x123456789A00  + offset +k;  
	     node_cfg.Node.link_mac  = 0x123456789B00  + offset +k;  			 
#else				
		 node_cfg.Node.sub_mac[0]   = 10+offset+k; 	
		 node_cfg.Node.link_mac[0]  = 80+offset+k; 			 
#endif
	     node_cfg.Node.sub_uid    = 1+offset +k;      // 节点编号	

		 iot_Node_Add( &node_cfg )	;

	}
		
	
	

//----添加组号1节点-------
   offset = 1;
   node_cfg.Node.group  = 1;
	 
	for(k=0;k<NODE95_TEST_GROUP_1_QT;k++)
	{
#if NODE_MAC_UINT64_ENABLE   
	     node_cfg.Node.sub_mac   = 0x123456789A00  + offset +k;  
	     node_cfg.Node.link_mac  = 0x123456789B00  + offset +k;  			 
#else				
		 node_cfg.Node.sub_mac[0]   = 10+offset+k; 	
		 node_cfg.Node.link_mac[0]  = 80+offset+k; 			 
#endif
	     node_cfg.Node.sub_uid    = 1+offset +k;      // 节点编号	

		 iot_Node_Add( &node_cfg )	;

	}
	
	
	
//------test ok-----	
	
//删除组节点
 iot_Node_DeleteGroup( 2 );
	
 iot_Node_DeleteGroup_ByType( 3, IOT_SENSOR_smoke);

 iot_Node_DeleteGroup_ByType( 3, IOT_SENSOR_liquid);




//删除组节点
 //iot_Node_DeleteGroup( 3 );	
	
//删除组节点
 //iot_Node_DeleteGroup( 1 );	
		
	

//清空所有配置节点
 //iot_Node_Clear( );

#endif

}








// (liquid_config_t*)pcfg ;
void iot_Node_WriteSensor(void* pcfg)
{


#if    IOTV30_thread_enable   //是否启用线程

 attr_pool_t      attr_obj;
 device_addr_un_t dev_addr_un ;
 //liquid_attr_t    liquid_obj; 

liquid_config_t*  liq_cfg = (liquid_config_t*)pcfg ;


   LOG_NAME();
   // typedef struct {
// 	unsigned char node_mac[6];
// 	unsigned char type_channel;
// 	unsigned char private_addr;
// }device_addr_t;
// typedef union {
// 	uint64_t mac_64;
// 	device_addr_t addr_st;
// }device_addr_un_t;

// typedef struct {
// 	unsigned short dpid;
// 	unsigned char data_type;
// 	unsigned char hex_len;       // 不管有没oct_len/delay_ms, 结构体都占用16字节
// 	unsigned int delay_ms;   // 用于pool数组执行时的每个item执行后的延时时间
// 	un_val_t un_val;
// }attr_pool_t;



  dev_addr_un.addr_st.private_addr =1 ;   ////modbus 地址，设备rs485通讯地址
  dev_addr_un.addr_st.type_channel =0x12 ; //TYPE_485_CH2 //高4位：主类型 ---低4位：副类型/通道号， 当主类型=485时，低4位为通道号

  //dev_addr_un.addr_st.node_mac[0]=1 ;
  dev_addr_un.addr_st.node_mac[0]=0xFF ;  //?????----///设备rs485通讯地址--645协议----或者PLC通讯地址
  dev_addr_un.addr_st.node_mac[1]=0xFF ;
  dev_addr_un.addr_st.node_mac[2]=0xFF ;
  dev_addr_un.addr_st.node_mac[3]=0xFF ;
  dev_addr_un.addr_st.node_mac[4]=0xFF ;
  dev_addr_un.addr_st.node_mac[5]=0xFF ;



// 0x0600	液位设备地址
// 0x0601	液位报警使能
	
// 0x0604	液位过低阈值
// 0x0605	液位过高阈值
// 0x0486	温度过低阈值
// 0x0487	温度过高阈值

// 0x0601,alarmEn,液位报警使能,0,0,0,uint32,0,0,0,0,0,0,cfgParam1,0x13
// 0x0604,thOlL,液位过低阈值,0.01mm,0,0,int32,0,0,0,0,0,0,cfgParam2,0x13
// 0x0605,thOlH,液位过高阈值,0.01mm,0,0,int32,0,0,0,0,0,0,cfgParam3,0x13
// 0x0486,thTL,温度过低阈值,duC,0,0,int32,0,0,0,0,0,0,cfgParam4,0x13
// 0x0487,thTH,温度过高阈值,duC,0,0,int32,0,0,0,0,0,0,cfgParam5,0x13


// cnt=3,dpid=0x601 ,data_type=3,un_val=0
// cnt=4,dpid=0x604 ,data_type=4,un_val=10000
// cnt=5,dpid=0x605 ,data_type=4,un_val=60000
// cnt=6,dpid=0x486 ,data_type=4,un_val=0
// cnt=7,dpid=0x487 ,data_type=4,un_val=0


	attr_obj.dpid     = 0x0601 ;
	attr_obj.data_type = 3 ;
	attr_obj.un_val.vu32 = liq_cfg->alarm_enable.value ;

   if( rs485_attr_set_one_by_dpid( &dev_addr_un, 0x0601, &attr_obj ) <0 )
   {
       printf(" WriteSensor fail!cnt=%d,dpid=0x%x ,data_type=%d,un_val=%d\n",attr_obj.dpid ,attr_obj.data_type,attr_obj.un_val.vu32 );	
   }


	attr_obj.dpid     = 0x0604 ;
	attr_obj.data_type = 4 ;
	attr_obj.un_val.vu32 = liq_cfg->under_level_th ;
   if( rs485_attr_set_one_by_dpid( &dev_addr_un, 0x0604, &attr_obj ) <0 )
   {
       printf(" WriteSensor fail!cnt=%d,dpid=0x%x ,data_type=%d,un_val=%d\n",attr_obj.dpid ,attr_obj.data_type,attr_obj.un_val.vu32 );	
   }



	attr_obj.dpid     = 0x0605 ;
	attr_obj.data_type = 4 ;
	attr_obj.un_val.vu32 = liq_cfg->over_level_th ;
   if( rs485_attr_set_one_by_dpid( &dev_addr_un, 0x0605, &attr_obj ) <0 )
   {
       printf(" WriteSensor fail!cnt=%d,dpid=0x%x ,data_type=%d,un_val=%d\n",attr_obj.dpid ,attr_obj.data_type,attr_obj.un_val.vu32 );	
   }



	attr_obj.dpid     = 0x0486 ;
	attr_obj.data_type = 4 ;
	attr_obj.un_val.vu32 = liq_cfg->under_temper_th ;
   if( rs485_attr_set_one_by_dpid( &dev_addr_un, 0x0486, &attr_obj ) <0 )
   {
       printf(" WriteSensor fail!cnt=%d,dpid=0x%x ,data_type=%d,un_val=%d\n",attr_obj.dpid ,attr_obj.data_type,attr_obj.un_val.vu32 );	
   }


	attr_obj.dpid     = 0x0487 ;
	attr_obj.data_type = 4 ;
	attr_obj.un_val.vu32 = liq_cfg->over_temper_th ;
   if( rs485_attr_set_one_by_dpid( &dev_addr_un, 0x0487, &attr_obj ) <0 )
   {
       printf(" WriteSensor fail!cnt=%d,dpid=0x%x ,data_type=%d,un_val=%d\n",attr_obj.dpid ,attr_obj.data_type,attr_obj.un_val.vu32 );	
   }

	liq_cfg = NULL;



#endif	

}




//dpid
// 0x0601	液位报警使能	 data_type=3
// 0x0604	液位过低阈值     data_type=4
// 0x0605	液位过高阈值     data_type=4
// 0x0486	温度过低阈值     data_type=4
// 0x0487	温度过高阈值     data_type=4
//1,0x12, 3 or 4 
uint8_t  iot_Node_WriteSensor_one( uint8_t dev_addr, uint8_t chan,uint8_t data_type, uint16_t dpid, uint32_t value)
{

#if    IOTV30_thread_enable   //是否启用线程

 attr_pool_t      attr_obj;

 device_addr_un_t dev_addr_un ;

   LOG_NAME();


 // dev_addr_un.addr_st.private_addr =1 ;   ////modbus 地址，设备rs485通讯地址
 // dev_addr_un.addr_st.type_channel =0x12 ; //TYPE_485_CH2 //高4位：主类型 ---低4位：副类型/通道号， 当主类型=485时，低4位为通道号

  dev_addr_un.addr_st.private_addr = dev_addr ;   ////modbus 地址，设备rs485通讯地址
  dev_addr_un.addr_st.type_channel = chan ; //TYPE_485_CH2 //高4位：主类型 ---低4位：副类型/通道号， 当主类型=485时，低4位为通道号


  //dev_addr_un.addr_st.node_mac[0]=1 ;
  dev_addr_un.addr_st.node_mac[0]=0xFF ;  //?????----///设备rs485通讯地址--645协议----或者PLC通讯地址
  dev_addr_un.addr_st.node_mac[1]=0xFF ;
  dev_addr_un.addr_st.node_mac[2]=0xFF ;
  dev_addr_un.addr_st.node_mac[3]=0xFF ;
  dev_addr_un.addr_st.node_mac[4]=0xFF ;
  dev_addr_un.addr_st.node_mac[5]=0xFF ;



// 0x0600	液位设备地址
// 0x0601	液位报警使能
	
// 0x0604	液位过低阈值
// 0x0605	液位过高阈值
// 0x0486	温度过低阈值
// 0x0487	温度过高阈值

// 0x0601,alarmEn,液位报警使能,0,0,0,uint32,0,0,0,0,0,0,cfgParam1,0x13
// 0x0604,thOlL,液位过低阈值,0.01mm,0,0,int32,0,0,0,0,0,0,cfgParam2,0x13
// 0x0605,thOlH,液位过高阈值,0.01mm,0,0,int32,0,0,0,0,0,0,cfgParam3,0x13
// 0x0486,thTL,温度过低阈值,duC,0,0,int32,0,0,0,0,0,0,cfgParam4,0x13
// 0x0487,thTH,温度过高阈值,duC,0,0,int32,0,0,0,0,0,0,cfgParam5,0x13


// cnt=3,dpid=0x601 ,data_type=3,un_val=0
// cnt=4,dpid=0x604 ,data_type=4,un_val=10000
// cnt=5,dpid=0x605 ,data_type=4,un_val=60000
// cnt=6,dpid=0x486 ,data_type=4,un_val=0
// cnt=7,dpid=0x487 ,data_type=4,un_val=0



	attr_obj.dpid        = dpid ;
	attr_obj.data_type   = data_type ;
	attr_obj.un_val.vu32 = value ;
   if( rs485_attr_set_one_by_dpid( &dev_addr_un, dpid, &attr_obj ) <0 )
   {
       printf(" WriteSensor fail!dpid=0x%x ,data_type=%d,un_val=%d\n",attr_obj.dpid ,attr_obj.data_type,attr_obj.un_val.vu32 );
	   return 0;	
   }

       printf(" WriteSensor ok!dpid=0x%x ,data_type=%d,un_val=%d\n",attr_obj.dpid ,attr_obj.data_type,attr_obj.un_val.vu32 );

#endif


	 return 1;

}



/*************************************************************************************************
function: rs485_read_one_attr_by_dpid() 通过dpid读设备属性
param:  *pdev_addr_un:   设备id
        dpid:     属性id
return:  attr_pool_t * 返回属性池指针， 调用方使用完需释放        
*************************************************************************************************/

/// 主动轮询节点的周期时间--这个需要小于等于-#define  TLV_ReportPeriod_sec   ( 2*60 )   -否则意义不大  
void iot_Node_Test_tick_min(void)
{
static uint8_t loop_idx = 0;
uint8_t num;
dev_mod_info_t dev_mod_info;

   LOG_NAME();


//返回值 0---链接断开，  1---链接成功
 if( 0== gw_ktj_IsTcpClientConnected() )
 {
    return ;
 }


//  uint8_t node_num = iot_Node_GetNum( );

//    for(uint8_t idx=0;idx< node_num;idx++)
//    {
//        liquid_test_tick_min( idx);
//    }



	num = iot_Node_GetNum();
	if(num == 0)
	{////白名单没有节点就不轮询了
		printf("whitelist is null,no readAttr\n");
		return;
	}

    
	if(loop_idx >= num )
	{
	   loop_idx = 0;
	}
	
	printf("loop_idx=%d\n",loop_idx);

	if(0==iot_get_mod_info_with_index( loop_idx++ , &dev_mod_info) )  ////每次(sec)只读1个节点????
	{
		printf("get mod info fail\n");
        return ;
	}



	dev_mod_info.node_type = 1;   ////这里与上行协议不一样---json协议对应的是485固定为1----s


//"nodeType":1,"channel":2,"privAddr":1,
//   dev_mod_info.node_type = 1;
//   dev_mod_info.chan_addr = 1;
//   dev_mod_info.channel = 2;
                                                                               //这里json协议对应的是485固定为1----
  json_readAttr_single(dev_mod_info.chan_addr , dev_mod_info.channel, 1); //dev_mod_info.node_type -----周期读暂时屏蔽掉



#if  0

 //attr_pool_t *  pattr =NULL;
 //device_addr_un_t dev_addr_un ;
 liquid_attr_t   liquid_obj; 
 int dpid ;

//int8_t temper ;
//uint32_t liquid ,alarmStatus;

	unsigned int cnt, read_attr_num=0;



#if  0

 uint8_t node_num = iot_Node_GetNum( );

   for(uint8_t idx=0;idx< node_num;idx++)
   {
       liquid_test_tick_min( idx);
   }

#endif



// 0x0500	液位报警信息	RO	是	运行参数	uint32_t			0	"0=正常，1=告警
// bit0：液位过低
// bit1：液位过高
// bit2：温度过低
// bit3：温度过高
// 其余：保留"
// 0x0501	液位	RO	否	运行参数	uint32_t		0.01mm		
// 0x0030	温度	RO	否	运行参数	int8_t	-128~127	1℃		
									
									
// 0x0600	液位设备地址	R/W	否	配置参数	uint8_t	0~255		1	
// 0x0601	液位报警使能	R/W	否	配置参数	uint32_t			0	"0=不启用，1=启用



  dev_addr_un.addr_st.private_addr = 1 ;   ////modbus 地址，设备rs485通讯地址
  dev_addr_un.addr_st.type_channel = 0x12 ; //TYPE_485_CH2 //高4位：主类型 ---低4位：副类型/通道号， 当主类型=485时，低4位为通道号

  //dev_addr_un.addr_st.node_mac[0]=1 ;
  dev_addr_un.addr_st.node_mac[0]=0xFF ;  //?????----///设备rs485通讯地址--645协议----或者PLC通讯地址
  dev_addr_un.addr_st.node_mac[1]=0xFF ;
  dev_addr_un.addr_st.node_mac[2]=0xFF ;
  dev_addr_un.addr_st.node_mac[3]=0xFF ;
  dev_addr_un.addr_st.node_mac[4]=0xFF ;
  dev_addr_un.addr_st.node_mac[5]=0xFF ;

   pattr = attr_read_all_item_std( &dev_addr_un, &read_attr_num );

   if(NULL != pattr)
   {
		printf("rs485_read_attr_dpid ok\n");

	//printf("get ........ num=%d, pool=0x%x\n", read_attr_num, pattr_pool_get);
	//print_attr_pool_by_addr_un(pattr_pool_get, read_attr_num, &device_addr_un);
	

        //  for(cnt=0;cnt< read_attr_num;cnt++)
		//  {
		//    printf("cnt=%d,dpid=0x%x ,data_type=%d,un_val=%d\n",cnt,pattr[cnt].dpid ,pattr[cnt].data_type,pattr[cnt].un_val.vu32 );	
		//  }
        cnt = 14;
        printf("cnt=%d,dpid=0x%x ,data_type=%d,un_val=%d\n",cnt,pattr[cnt].dpid ,pattr[cnt].data_type,pattr[cnt].un_val.vu32 );	

        cnt = 16;
        printf("cnt=%d,dpid=0x%x ,data_type=%d,un_val=%d\n",cnt,pattr[cnt].dpid ,pattr[cnt].data_type,pattr[cnt].un_val.vu32 );	

	    cnt = 21;
        printf("cnt=%d,dpid=0x%x ,data_type=%d,un_val=%d\n",cnt,pattr[cnt].dpid ,pattr[cnt].data_type,pattr[cnt].un_val.vu32 );		


        memset((uint8_t*)&liquid_obj,0,sizeof(liquid_attr_t) );



// 0x0601,alarmEn,液位报警使能,0,0,0,uint32,0,0,0,0,0,0,cfgParam1,0x13
// 0x0604,thOlL,液位过低阈值,0.01mm,0,0,int32,0,0,0,0,0,0,cfgParam2,0x13
// 0x0605,thOlH,液位过高阈值,0.01mm,0,0,int32,0,0,0,0,0,0,cfgParam3,0x13
// 0x0486,thTL,温度过低阈值,duC,0,0,int32,0,0,0,0,0,0,cfgParam4,0x13
// 0x0487,thTH,温度过高阈值,duC,0,0,int32,0,0,0,0,0,0,cfgParam5,0x13


// cnt=3,dpid=0x601 ,data_type=3,un_val=0
// cnt=4,dpid=0x604 ,data_type=4,un_val=10000
// cnt=5,dpid=0x605 ,data_type=4,un_val=60000
// cnt=6,dpid=0x486 ,data_type=4,un_val=0
// cnt=7,dpid=0x487 ,data_type=4,un_val=0


        liquid_obj.config.alarm_enable.value = pattr[3].un_val.vu32 ;
        liquid_obj.config.under_level_th     = pattr[4].un_val.vu32 ;
        liquid_obj.config.over_level_th      = pattr[5].un_val.vu32 ;
        liquid_obj.config.under_temper_th    = pattr[6].un_val.vu32 ;
        liquid_obj.config.over_temper_th     = pattr[7].un_val.vu32 ;

        liquid_obj.data.temper      =   pattr[14].un_val.vs32 ;//1℃-上报温度--dpid=0x30 
        liquid_obj.data.level_mm    =   pattr[16].un_val.vu32 ;//0.01mm---dpid=0x501 ,data_type=4,un_val=72504-----------上报液位-----------
        liquid_obj.data.alarm.value =   pattr[21].un_val.vu32 ;// cnt=21,dpid=0x500 ,data_type=3,un_val=10-----报警信息-----------

		printf("temper=%d,liquid=%d ,alarmStatus=0x%04x\n", liquid_obj.data.temper, liquid_obj.data.level_mm, liquid_obj.data.alarm.value );	//0x11b38
		printf("alarm_enable=0x%04x\n", liquid_obj.config.alarm_enable.value );
		printf("under_level_th=%d,over_level_th=%d\n",liquid_obj.config.under_level_th , liquid_obj.config.over_level_th );
		printf("under_temper_th=%d,over_temper_th=%d\n",liquid_obj.config.under_temper_th , liquid_obj.config.over_temper_th );


        free(pattr);
		pattr = NULL;
   }else{
        printf("rs485_read_attr_dpid=0x%x error\n",pattr->dpid);

   }



// 0x0501,rpt_ol,上报液位,0.01mm,0,0,int32,0,0,0,100,1,0,ol,0x13
// 0x0030,rpt_t,上报温度,duC,0,0,int32,0,0,0,1,1,1,t,0x13
//0x0500	alarmStatus	液位计报警信息	0	0	0	uint32

#if 0
  dpid = 0x0501; //rpt_ol,上报液位
   pattr = rs485_read_one_attr_by_dpid(  &dev_addr_un,  dpid);

   if(NULL != pattr)
   {
		printf("rs485_read_attr_dpid ok\n");
		printf("dpid=0x%x ,data_type=%d,un_val=%d\n",pattr->dpid ,pattr->data_type,pattr->un_val.vu32 );	

        liquid = pattr->un_val.vu32 ;//0.01mm

        free(pattr);
		pattr = NULL;
   }else{
        printf("rs485_read_attr_dpid=0x%x error\n",pattr->dpid);

   }


   dpid = 0x0030; // 0x0030,rpt_t,上报温度,
   pattr = rs485_read_one_attr_by_dpid(  &dev_addr_un,  dpid);

   if(NULL != pattr)
   {
		printf("rs485_read_attr_dpid ok\n");
		printf("dpid=0x%x ,data_type=%d,un_val=%d\n",pattr->dpid ,pattr->data_type,pattr->un_val.vu32 );		
        temper = pattr->un_val.vu32 ;

        free(pattr);
		pattr = NULL;
   }else{
       printf("rs485_read_attr_dpid=0x%x error\n",pattr->dpid);

   }

   dpid = 0x0500; // alarmStatus	液位计报警信息
   pattr = rs485_read_one_attr_by_dpid(  &dev_addr_un,  dpid);

   if(NULL != pattr)
   {
		printf("rs485_read_attr_dpid ok\n");
		printf("dpid=0x%x ,data_type=%d,un_val=%d\n",pattr->dpid ,pattr->data_type,pattr->un_val.vu32 );		
        alarmStatus = pattr->un_val.vu32 ;

        free(pattr);
		pattr = NULL;
   }else{
       printf("rs485_read_attr_dpid=0x%x error\n",pattr->dpid);

   }


#endif

#if   0 //////寄存器原始值

// 0x8000,olH,液位高,0,3,0,uint16,0x04,12,0,1,1,0,0,0x13
// 0x8001,olL,液位低,0,3,0,uint16,0x05,12,0,1,1,0,0,0x13
// 0x8002,tempeR,温度1,0,3,0,int16,0x06,12,0,1,1,0,0,0x13
// 0x0600,mbAddr,地址,0,3,6,uint16,0x20,12,0,1,1,0,0,0
// 0x8003,ol,液位,0,0,0,float,0,0,0,1,1,0,(olH*10000+olL)/10000,0x13
// 0x8004,t,温度,duC,0,0,float,0,0,0,1,16,0,tempe,0x13

  dpid = 0x8000; //olH,液位
   pattr = rs485_read_one_attr_by_dpid(  &dev_addr_un,  dpid);

   if(NULL != pattr)
   {
        //pattr[0]
		printf("rs485_read_attr_dpid ok\n");
       // printf("%s\n",pattr);

		printf("dpid=0x%x ,data_type=%d,un_val=%d\n",pattr->dpid ,pattr->data_type,pattr->un_val.vu32 );	
                     //dpid=0x8000 ,data_type=1,un_val=114

		//printf("dpid=0x%x ,data_type=%d,un_val=%f\n",pattr->dpid ,pattr->data_type,pattr->un_val.vfloat );	
        liquid = pattr->un_val.vu32 *10000;//0.01mm

        free(pattr);
		pattr = NULL;
   }else{
        printf("rs485_read_attr_dpid=0x%x error\n",pattr->dpid);

   }


  dpid = 0x8001; //olL,液位
   pattr = rs485_read_one_attr_by_dpid(  &dev_addr_un,  dpid);

   if(NULL != pattr)
   {
		printf("rs485_read_attr_dpid ok\n");
		printf("dpid=0x%x ,data_type=%d,un_val=%d\n",pattr->dpid ,pattr->data_type,pattr->un_val.vu32 );	

        liquid += pattr->un_val.vu32 ;//0.0001mm
        liquid /= 100 ;//0.01mm

        free(pattr);
		pattr = NULL;
   }else{
       printf("rs485_read_attr_dpid=0x%x error\n",pattr->dpid);

   }


   dpid = 0x8002; //tempeR,温度
   pattr = rs485_read_one_attr_by_dpid(  &dev_addr_un,  dpid);

   if(NULL != pattr)
   {
		printf("rs485_read_attr_dpid ok\n");
		printf("dpid=0x%x ,data_type=%d,un_val=%d\n",pattr->dpid ,pattr->data_type,pattr->un_val.vu32 );		
        temper = pattr->un_val.vu32/10 ;

        free(pattr);
		pattr = NULL;
   }else{
       printf("rs485_read_attr_dpid=0x%x error\n",pattr->dpid);

   }



#if 0
  dpid = 0x8003; //ol,液位
   pattr = rs485_read_one_attr_by_dpid(  &dev_addr_un,  dpid);

   if(NULL != pattr)
   {
        //pattr[0]
		printf("rs485_read_attr_dpid ok\n");
       // printf("%s\n",pattr);

		//printf("dpid=0x%x ,data_type=%d,un_val=%d\n",pattr->dpid ,pattr->data_type,pattr->un_val.vu32 );	
                     //dpid=0x8000 ,data_type=1,un_val=114


	// unsigned int vu32;
	// int vs32;
	// float vfloat;

		printf("dpid=0x%x ,data_type=%d,un_val=%f\n",pattr->dpid ,pattr->data_type,pattr->un_val.vfloat );	
       // liquid = pattr->un_val.vfloat *100;//0.01mm

        free(pattr);
		pattr = NULL;
   }else{
       printf("rs485_read_attr_dpid=0x%x error\n",pattr->dpid);

   }


  dpid = 0x8004; //0x8004,t,温度
   pattr = rs485_read_one_attr_by_dpid(  &dev_addr_un,  dpid);

   if(NULL != pattr)
   {
		printf("rs485_read_attr_dpid ok\n");
		printf("dpid=0x%x ,data_type=%d,un_val=%f\n",pattr->dpid ,pattr->data_type,pattr->un_val.vfloat );	
       // temper = pattr->un_val.vfloat ;  //1℃

        free(pattr);
		pattr = NULL;
   }else{
       printf("rs485_read_attr_dpid=0x%x error\n",pattr->dpid);

   }

#endif



#endif



 printf("rs485_read_attr_dpid done\n");

 uint8_t node_num = iot_Node_GetNum( );

   for(uint8_t idx=0;idx< node_num;idx++)
   {   
	   ////刷新节点运行数据-----  alarmStatus	液位计报警信息
 //      liquid_update_tick_min( idx, temper , liquid );
       liquid_obj_update(  idx, &liquid_obj );
   }

#endif


}



////模拟测试ok---------
void iot_Node_Test_tick_min_simu(void)
{
 uint8_t node_num = iot_Node_GetNum( );

   LOG_NAME();

   for(uint8_t idx=0;idx< node_num;idx++)
   {
       liquid_test_tick_min( idx);
   }

}




//#define dev_mac_u64(mac_array) ((uint64_t)mac_array[0] | (uint64_t)mac_array[1] << 8 | (uint64_t)mac_array[2] << 16 | (uint64_t)mac_array[3] << 24 | (uint64_t)mac_array[4] << 32 | (uint64_t)mac_array[5] << 40)


uint64_t iot_mac_to_uint64(uint8_t*  mac )
{
  uint8_t i;
  uint64_t  u64_mac =0;

  u64_mac = mac[0];

  for(i=1;i<NODE_ID_LEN;i++)
  {
    u64_mac =  u64_mac<<8 | mac[i];
  }

  return u64_mac;

}





void iot_uint64_to_mac(uint64_t u64_mac, uint8_t*  mac )
{
  uint8_t i;
  //uint64_t  u64_mac =0;

  u64_mac = mac[0];

  for(i=1;i<NODE_ID_LEN;i++)
  {
    u64_mac =  u64_mac<<8 | mac[i];
  }

}











